/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.allerj.analysis;

import blobDetection.Blob;

/**
 *
 * @author Alessandro Veracchi
 */
public class BlobFoodFilter implements BlobFilter{

    private float bbox_area;
    
    public int imageHeight;
    public int imageWidth;
    public int row;
    public int col;    
    public float whRatioTolerance = 0.3f;
    public float minAreaTolerancePerc = 30;
    public float maxAreaTolerancePerc = 90;
    
    public boolean newBlobDetectedEvent(Blob b) {

        // de-normalize h and w of the blob bounding box
        float bbox_h = b.h * imageHeight;
        float bbox_w = b.w * imageWidth;
        
        // compute bbox area
        bbox_area = bbox_w * bbox_h;
                                    
        // return value
        boolean isGood = false;
        
        // begin checks
        
        // check blob bounding box area
        if (!checkArea()) {
            isGood = false;
        }
        // blob area should look like a circle, so diameters must be quite equal
        else if (!checkCircularity(b, bbox_h, bbox_w)) {
            isGood = false;
        }
        else {
            isGood = true;
        }

        return isGood;
    }

    /**
     * The blob bounding box should be quite a perfect square, so that 
     * probabilities for blob of being a circle are high
     * 
     * @param diam1
     * @param diam2
     * @return
     */
    private boolean checkCircularity(Blob blob, float w, float h) {
        // avoid calculating area if bounding box is not quite a square
        float ratio = w / h;
        if ((ratio < 1-whRatioTolerance) || (ratio > 1+whRatioTolerance)) {
            return false;
        }
        
        return true;

        /*
         * following is commented because blob filter should perform only a
         * rough filtering. Deeper analysis goes into DotMark class

        // pick minimum between w and h
        float radius = (w<h) ? w : h;
        
        // compute area of the inscribed circle
        float insArea = (float) (Math.pow(radius, 2) * Math.PI);
        
        // compute area of the blob polygon
        float area = 0;
        for (int m=0; m<blob.getEdgeNb()-1 ;m++) {
            EdgeVertex vertex1 = blob.getEdgeVertexA(m);
            EdgeVertex vertex2 = blob.getEdgeVertexA(m+1);
            
            if ((vertex1 == null)||(vertex2==null)) {
                continue;
            }
            
            // remember! vertex are [0,1] normalized
            area += (vertex1.x * imageWidth) * (vertex2.y * imageHeight);
            area -= (vertex2.x * imageWidth) * (vertex1.y * imageHeight);
        }
        
        // area could be negative
        area = Math.abs(area / 2);
        
        // determine ratio
        System.out.println("circle area: "+insArea+", poly area: "+area);
        ratio = (float) Math.abs(insArea / area);

        
        // compute perimeter of the inscribed circle
        float insPer = 2 * (float) Math.PI * radius;
        
        // compute perimeter of the blob perimeter
        float per = 0;
        for (int m=0; m<blob.getEdgeNb(); m++) {
            EdgeVertex vertex_a = blob.getEdgeVertexA(m);
            EdgeVertex vertex_b = blob.getEdgeVertexB(m);
            if ((vertex_a == null)||(vertex_b == null)) continue;
            
            float ex = (vertex_b.x*imageWidth - vertex_a.x*imageWidth);
            float ey = (vertex_b.y*imageHeight - vertex_a.y*imageHeight);
            
            per += (float) Math.sqrt(Math.pow(ex, 2)+Math.pow(ey, 2));
        } 

        System.out.println("circle perimeter: "+insPer+", poly perimeter: "+per);
        ratio = (float) Math.abs(insPer / per);
        
        return (ratio>0.8) && (ratio<1.2);
        */
    }
        
    /**
     * The area of the blob bounding box should be between minAreaSizeTolerance 
     * and minAreaSizeTolerance in percentual of the entire image
     * 
     * @return success
     */
    private boolean checkArea() {
        float image_area = imageWidth * imageHeight;
        float percent = (bbox_area * 100) / image_area;
        
        return (percent > minAreaTolerancePerc) && 
                (percent < maxAreaTolerancePerc);
    }
}
